package com.example.demo.controller;

import com.example.demo.common.Result;
import com.example.demo.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * Redis测试控制器
 * @author Logan.Li
 */
@RestController
@RequestMapping("/api/redis")
@CrossOrigin(origins = "*")
public class RedisController {

    @Autowired
    private RedisService redisService;

    @Autowired
    private Environment environment;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 测试Redis连接
     */
    @GetMapping("/ping")
    public Result<String> ping() {
        try {
            String key = "ping";
            String value = "pong";
            redisService.set(key, value, 60, TimeUnit.SECONDS);
            Object result = redisService.get(key);
            return Result.success("Redis连接成功: " + result);
        } catch (Exception e) {
            return Result.error("Redis连接失败: " + e.getMessage());
        }
    }

    /**
     * 设置缓存
     */
    @PostMapping("/set")
    public Result<String> set(@RequestBody Map<String, Object> request) {
        try {
            String key = (String) request.get("key");
            String value = (String) request.get("value");
            Integer expire = (Integer) request.get("expire");
            
            if (expire != null && expire > 0) {
                redisService.set(key, value, expire, TimeUnit.SECONDS);
            } else {
                redisService.set(key, value);
            }
            return Result.success("设置成功");
        } catch (Exception e) {
            return Result.error("设置失败: " + e.getMessage());
        }
    }

    /**
     * 设置字符串缓存 - 避免序列化问题
     */
    @PostMapping("/setString")
    public Result<String> setString(@RequestBody Map<String, Object> request) {
        String key = (String) request.get("key");
        String value = (String) request.get("value");
        int db = request.containsKey("db") ? (Integer) request.get("db") : 0;
        
        RedisConnection connection = null;
        try {
            // 参数验证
            if (key == null || key.trim().isEmpty()) {
                return Result.error("缓存键不能为空");
            }
            if (value == null) {
                return Result.error("缓存值不能为空");
            }
            
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 使用同一连接进行操作
            connection.set(key.getBytes(), value.getBytes());
            
            return Result.success("设置字符串缓存成功");
        } catch (Exception e) {
            return Result.error("设置字符串缓存失败: " + e.getMessage());
        } finally {
            // 确保连接被正确关闭
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 获取缓存
     */
    @GetMapping("/get/{key}")
    public Result<Object> get(@PathVariable String key) {
        try {
            Object value = redisService.get(key);
            if (value == null) {
                return Result.error("键不存在或已过期");
            }
            return Result.success(value);
        } catch (Exception e) {
            return Result.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取字符串缓存 - 避免序列化问题
     */
    @GetMapping("/getString")
    public Result<String> getString(@RequestParam String key, @RequestParam(defaultValue = "0") int db) {
        RedisConnection connection = null;
        try {
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 使用同一连接进行操作
            byte[] valueBytes = connection.get(key.getBytes());
            String value = valueBytes != null ? new String(valueBytes) : null;
            
            if (value == null) {
                return Result.error("键不存在或已过期");
            }
            return Result.success(value);
        } catch (Exception e) {
            return Result.error("获取字符串缓存失败: " + e.getMessage());
        } finally {
            // 确保连接被正确关闭
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 设置List缓存
     */
    @PostMapping("/setList")
    public Result<String> setList(@RequestBody Map<String, Object> request) {
        String key = (String) request.get("key");
        @SuppressWarnings("unchecked")
        List<String> items = (List<String>) request.get("items");
        int db = request.containsKey("db") ? (Integer) request.get("db") : 0;
        
        RedisConnection connection = null;
        try {
            // 参数验证
            if (key == null || key.trim().isEmpty()) {
                return Result.error("缓存键不能为空");
            }
            if (items == null || items.isEmpty()) {
                return Result.error("List项目不能为空");
            }
            
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 先删除已存在的key
            connection.del(key.getBytes());
            
            // 添加List项目
            for (String item : items) {
                connection.rPush(key.getBytes(), item.getBytes());
            }
            
            return Result.success("设置List缓存成功");
        } catch (Exception e) {
            return Result.error("设置List缓存失败: " + e.getMessage());
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 设置Set缓存
     */
    @PostMapping("/setSet")
    public Result<String> setSet(@RequestBody Map<String, Object> request) {
        String key = (String) request.get("key");
        @SuppressWarnings("unchecked")
        List<String> members = (List<String>) request.get("members");
        int db = request.containsKey("db") ? (Integer) request.get("db") : 0;
        
        RedisConnection connection = null;
        try {
            // 参数验证
            if (key == null || key.trim().isEmpty()) {
                return Result.error("缓存键不能为空");
            }
            if (members == null || members.isEmpty()) {
                return Result.error("Set成员不能为空");
            }
            
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 先删除已存在的key
            connection.del(key.getBytes());
            
            // 添加Set成员
            byte[][] memberBytes = members.stream()
                .map(String::getBytes)
                .toArray(byte[][]::new);
            connection.sAdd(key.getBytes(), memberBytes);
            
            return Result.success("设置Set缓存成功");
        } catch (Exception e) {
            return Result.error("设置Set缓存失败: " + e.getMessage());
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 设置Hash缓存
     */
    @PostMapping("/setHash")
    public Result<String> setHash(@RequestBody Map<String, Object> request) {
        String key = (String) request.get("key");
        String field = (String) request.get("field");
        String value = (String) request.get("value");
        int db = request.containsKey("db") ? (Integer) request.get("db") : 0;
        
        RedisConnection connection = null;
        try {
            // 参数验证
            if (key == null || key.trim().isEmpty()) {
                return Result.error("缓存键不能为空");
            }
            if (field == null || field.trim().isEmpty()) {
                return Result.error("Hash字段不能为空");
            }
            if (value == null) {
                return Result.error("Hash值不能为空");
            }
            
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 使用同一连接进行Hash操作
            connection.hSet(key.getBytes(), field.getBytes(), value.getBytes());
            
            return Result.success("设置Hash缓存成功");
        } catch (Exception e) {
            return Result.error("设置Hash缓存失败: " + e.getMessage());
        } finally {
            // 确保连接被正确关闭
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 设置ZSet缓存
     */
    @PostMapping("/setZSet")
    public Result<String> setZSet(@RequestBody Map<String, Object> request) {
        String key = (String) request.get("key");
        String member = (String) request.get("member");
        Double score = request.get("score") instanceof Number ? 
            ((Number) request.get("score")).doubleValue() : 
            Double.parseDouble(request.get("score").toString());
        int db = request.containsKey("db") ? (Integer) request.get("db") : 0;
        
        RedisConnection connection = null;
        try {
            // 参数验证
            if (key == null || key.trim().isEmpty()) {
                return Result.error("缓存键不能为空");
            }
            if (member == null || member.trim().isEmpty()) {
                return Result.error("ZSet成员不能为空");
            }
            if (score == null) {
                return Result.error("ZSet分数不能为空");
            }
            
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 使用同一连接进行ZSet操作
            connection.zAdd(key.getBytes(), score, member.getBytes());
            
            return Result.success("设置ZSet缓存成功");
        } catch (Exception e) {
            return Result.error("设置ZSet缓存失败: " + e.getMessage());
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 删除缓存
     */
    @DeleteMapping("/delete/{key}")
    public Result<Boolean> delete(@PathVariable String key) {
        try {
            Boolean result = redisService.delete(key);
            return Result.success(result);
        } catch (Exception e) {
            return Result.error("删除失败: " + e.getMessage());
        }
    }

    /**
     * 获取所有缓存键 - 支持分页，生产环境限制全局扫描
     */
    @GetMapping("/keys")
    public ResponseEntity<Map<String, Object>> getKeys(
            @RequestParam(defaultValue = "*") String pattern,
            @RequestParam(defaultValue = "0") int db,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "50") int size) {
        Map<String, Object> response = new HashMap<>();
        RedisConnection connection = null;
        
        try {
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 生产环境限制
            if (isProductionEnvironment()) {
                if ("*".equals(pattern)) {
                    response.put("success", false);
                    response.put("message", "生产环境禁止使用通配符 * 查询所有键");
                    response.put("data", new HashMap<>());
                    return ResponseEntity.ok(response);
                }
                // 生产环境限制每页大小
                if (size > 50) {
                    size = 50;
                }
            }
            
            // 使用同一连接获取键
            Set<byte[]> keyBytes = connection.keys(pattern.getBytes());
            List<String> keyList = new ArrayList<>();
            if (keyBytes != null) {
                for (byte[] keyByte : keyBytes) {
                    keyList.add(new String(keyByte));
                }
            }
            
            // 分页处理
            int total = keyList.size();
            int totalPages = (int) Math.ceil((double) total / size);
            int startIndex = (page - 1) * size;
            int endIndex = Math.min(startIndex + size, total);
            
            List<String> pagedKeys = new ArrayList<>();
            if (startIndex < total) {
                pagedKeys = keyList.subList(startIndex, endIndex);
            }
            
            // 分页响应数据
            Map<String, Object> pageData = new HashMap<>();
            pageData.put("keys", pagedKeys);
            pageData.put("total", total);
            pageData.put("page", page);
            pageData.put("size", size);
            pageData.put("totalPages", totalPages);
            pageData.put("hasNext", page < totalPages);
            pageData.put("hasPrev", page > 1);
            
            response.put("success", true);
            response.put("data", pageData);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            response.put("success", false);
            response.put("message", "获取键失败: " + e.getMessage());
            response.put("data", new HashMap<>());
            return ResponseEntity.ok(response);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 获取Redis基础信息
     */
    @GetMapping("/info")
    public Result<Map<String, Object>> info() {
        try {
            Map<String, Object> info = new HashMap<>();
            
            // 测试Redis连接
            String testKey = "test:info:" + System.currentTimeMillis();
            redisService.setString(testKey, "连接测试", 60, TimeUnit.SECONDS);
            String testValue = redisService.getString(testKey);
            
            // 获取Redis基础信息
            Properties redisInfo = redisTemplate.getConnectionFactory().getConnection().info();
            String redisVersion = redisInfo.getProperty("redis_version", "未知");
            String usedMemory = redisInfo.getProperty("used_memory_human", "未知");
            String connectedClients = redisInfo.getProperty("connected_clients", "0");
            
            // 判断Redis模式
            String mode = "单机模式";
            try {
                // 尝试获取集群信息
                RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
                if (connection instanceof RedisClusterConnection) {
                    ((RedisClusterConnection) connection).clusterGetNodes();
                    mode = "集群模式";
                }
            } catch (Exception ignored) {
                // 如果获取集群信息失败，说明是单机模式
            }
            
            info.put("mode", mode);
            info.put("version", redisVersion);
            info.put("memory", usedMemory);
            info.put("connections", Integer.parseInt(connectedClients));
            info.put("status", testValue != null ? "connected" : "disconnected");
            info.put("testResult", testValue != null ? "连接正常" : "连接异常");
            
            // 清理测试键
            redisService.delete(testKey);
            
            return Result.success(info);
        } catch (Exception e) {
            Map<String, Object> info = new HashMap<>();
            info.put("mode", "集群模式");
            info.put("version", "6.2+");
            info.put("memory", "未知");
            info.put("connections", 0);
            info.put("status", "error");
            info.put("testResult", "连接异常: " + e.getMessage());
            return Result.success(info);
        }
    }

    /**
     * 获取缓存（兼容旧接口）
     */
    @GetMapping("/get")
    public Result<Object> getByParam(@RequestParam String key, @RequestParam(defaultValue = "0") int db) {
        RedisConnection connection = null;
        try {
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 使用同一连接获取值
            byte[] valueBytes = connection.get(key.getBytes());
            String value = valueBytes != null ? new String(valueBytes) : null;
            
            if (value == null) {
                return Result.error("键不存在或已过期");
            }
            return Result.success(value);
        } catch (Exception e) {
            return Result.error("获取失败: " + e.getMessage());
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 删除缓存（兼容旧接口）
     */
    @DeleteMapping("/delete")
    public Result<Boolean> deleteByParam(@RequestParam String key, @RequestParam(defaultValue = "0") int db) {
        RedisConnection connection = null;
        try {
            // 获取连接并切换到指定数据库
            connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 使用同一连接删除键
            Long result = connection.del(key.getBytes());
            
            return Result.success(result > 0);
        } catch (Exception e) {
            return Result.error("删除失败: " + e.getMessage());
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    /**
     * 清空所有缓存 - 危险操作，完全禁用
     */
    @DeleteMapping("/clear")
    public Result<String> clearAll() {
        // 完全禁用清空缓存功能，无论任何环境
        return Result.error("清空缓存功能已被永久禁用，这是一个危险操作");
    }

    /**
     * 批量导出缓存数据
     * @param pattern 键名模式
     * @param db 数据库索引
     * @param format 导出格式 (json/csv)
     */
    @GetMapping("/export")
    public ResponseEntity<Map<String, Object>> exportCache(
            @RequestParam(defaultValue = "*") String pattern,
            @RequestParam(defaultValue = "0") int db,
            @RequestParam(defaultValue = "json") String format) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 切换到指定数据库
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            // 生产环境限制
            if (isProductionEnvironment() && "*".equals(pattern)) {
                response.put("success", false);
                response.put("message", "生产环境禁止导出所有缓存数据");
                connection.close();
                return ResponseEntity.ok(response);
            }
            
            Set<String> keys = redisTemplate.keys(pattern);
            
            // 限制导出数量，避免内存溢出
            int maxExportKeys = isProductionEnvironment() ? 1000 : 5000;
            if (keys.size() > maxExportKeys) {
                response.put("success", false);
                response.put("message", "导出数据量过大，请缩小范围。当前匹配 " + keys.size() + " 个键，最大允许 " + maxExportKeys + " 个");
                connection.close();
                return ResponseEntity.ok(response);
            }
            
            Map<String, Object> exportData = new HashMap<>();
            int successCount = 0;
            int errorCount = 0;
            
            // 批量获取键值对，使用限流避免Redis压力过大
            for (String key : keys) {
                try {
                    String value = redisService.getString(key);
                    if (value != null) {
                        exportData.put(key, value);
                        successCount++;
                    }
                    
                    // 每处理100个键暂停10ms，避免Redis压力过大
                    if (successCount % 100 == 0) {
                        Thread.sleep(10);
                    }
                } catch (Exception e) {
                    errorCount++;
                    System.out.println("导出键 " + key + " 失败: " + e.getMessage());
                }
            }
            
            connection.close();
            
            Map<String, Object> result = new HashMap<>();
            result.put("data", exportData);
            result.put("total", keys.size());
            result.put("successCount", successCount);
            result.put("errorCount", errorCount);
            result.put("pattern", pattern);
            result.put("database", db);
            result.put("exportTime", System.currentTimeMillis());
            result.put("format", format);
            
            response.put("success", true);
            response.put("data", result);
            response.put("message", "导出完成，成功: " + successCount + "，失败: " + errorCount);
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            response.put("success", false);
            response.put("message", "导出失败: " + e.getMessage());
            response.put("data", new HashMap<>());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 优化版导出缓存 - 支持流式下载和大数据量处理
     * @param pattern 键名模式
     * @param db 数据库索引
     * @param method 导出方式 (auto/json/stream/batch)
     * @author Logan.Li
     */
    @GetMapping("/export/optimized")
    public ResponseEntity<?> exportCacheOptimized(
            @RequestParam(defaultValue = "*") String pattern,
            @RequestParam(defaultValue = "0") int db,
            @RequestParam(defaultValue = "auto") String method,
            HttpServletResponse httpResponse) {
        
        try {
            // 预估数据量
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            Set<String> keys = redisTemplate.keys(pattern);
            int keyCount = keys.size();
            connection.close();
            
            // 生产环境限制
            if (isProductionEnvironment() && "*".equals(pattern) && keyCount > 10000) {
                Map<String, Object> response = new HashMap<>();
                response.put("success", false);
                response.put("message", "生产环境大数据量导出需要审批，请联系管理员");
                return ResponseEntity.ok(response);
            }
            
            // 智能选择导出方式
            if ("auto".equals(method)) {
                if (keyCount <= 1000) {
                    method = "json";
                } else if (keyCount <= 50000) {
                    method = "stream";
                } else {
                    method = "batch";
                }
            }
            
            switch (method) {
                case "json":
                    return exportAsJson(pattern, db, keyCount);
                case "stream":
                    return exportAsStreamFile(pattern, db, httpResponse);
                case "batch":
                    return exportAsBatchInfo(pattern, db, keyCount);
                default:
                    return exportAsJson(pattern, db, keyCount);
            }
            
        } catch (Exception e) {
            Map<String, Object> response = new HashMap<>();
            response.put("success", false);
            response.put("message", "导出失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * JSON格式导出（适用于小数据量）
     * @author Logan.Li
     */
    private ResponseEntity<Map<String, Object>> exportAsJson(String pattern, int db, int keyCount) {
        Map<String, Object> response = new HashMap<>();
        
        if (keyCount > 5000) {
            response.put("success", false);
            response.put("message", String.format("数据量过大(%d键)，建议使用流式导出", keyCount));
            response.put("suggestion", "使用 method=stream 参数进行流式导出");
            return ResponseEntity.ok(response);
        }
        
        try {
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            Set<String> keys = redisTemplate.keys(pattern);
            Map<String, Object> exportData = new HashMap<>();
            int successCount = 0;
            int errorCount = 0;
            
            for (String key : keys) {
                try {
                    String value = redisService.getString(key);
                    if (value != null) {
                        exportData.put(key, value);
                        successCount++;
                    }
                } catch (Exception e) {
                    errorCount++;
                }
            }
            
            connection.close();
            
            Map<String, Object> result = new HashMap<>();
            result.put("data", exportData);
            result.put("metadata", Map.of(
                "exportTime", System.currentTimeMillis(),
                "pattern", pattern,
                "database", db,
                "totalKeys", keyCount,
                "successCount", successCount,
                "errorCount", errorCount,
                "method", "json"
            ));
            
            response.put("success", true);
            response.put("data", result);
            response.put("message", String.format("JSON导出完成，成功: %d，失败: %d", successCount, errorCount));
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            response.put("success", false);
            response.put("message", "JSON导出失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 流式文件导出（适用于中大数据量）
     * @author Logan.Li
     */
    private ResponseEntity<?> exportAsStreamFile(String pattern, int db, HttpServletResponse httpResponse) {
        try {
            // 设置响应头为文件下载
            String fileName = String.format("redis_export_db%d_%d.json", db, System.currentTimeMillis());
            httpResponse.setContentType("application/json");
            httpResponse.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            Set<String> keys = redisTemplate.keys(pattern);
            
            // 使用流式写入，避免内存溢出
            try (PrintWriter writer = httpResponse.getWriter()) {
                writer.write("{\n");
                writer.write("  \"metadata\": {\n");
                writer.write("    \"exportTime\": " + System.currentTimeMillis() + ",\n");
                writer.write("    \"pattern\": \"" + pattern + "\",\n");
                writer.write("    \"database\": " + db + ",\n");
                writer.write("    \"totalKeys\": " + keys.size() + ",\n");
                writer.write("    \"method\": \"stream\"\n");
                writer.write("  },\n");
                writer.write("  \"data\": {\n");
                
                int count = 0;
                int successCount = 0;
                
                for (String key : keys) {
                    try {
                        String value = redisService.getString(key);
                        if (value != null) {
                            if (count > 0) {
                                writer.write(",\n");
                            }
                            // JSON转义
                            String escapedKey = key.replace("\"", "\\\"");
                            String escapedValue = value.replace("\"", "\\\"").replace("\n", "\\n");
                            writer.write("    \"" + escapedKey + "\": \"" + escapedValue + "\"");
                            successCount++;
                            count++;
                            
                            // 每1000条刷新一次，提供实时下载体验
                            if (count % 1000 == 0) {
                                writer.flush();
                                Thread.sleep(10); // 避免Redis压力过大
                            }
                        }
                    } catch (Exception e) {
                        System.err.println("导出键 " + key + " 失败: " + e.getMessage());
                    }
                }
                
                writer.write("\n  },\n");
                writer.write("  \"exportStats\": {\n");
                writer.write("    \"successCount\": " + successCount + ",\n");
                writer.write("    \"totalProcessed\": " + count + "\n");
                writer.write("  }\n");
                writer.write("}");
                writer.flush();
            }
            
            connection.close();
            return null; // 直接写入响应流，不返回ResponseEntity
            
        } catch (Exception e) {
            Map<String, Object> response = new HashMap<>();
            response.put("success", false);
            response.put("message", "流式导出失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 分批导出信息（适用于超大数据量）
     * @author Logan.Li
     */
    private ResponseEntity<Map<String, Object>> exportAsBatchInfo(String pattern, int db, int keyCount) {
        Map<String, Object> response = new HashMap<>();
        
        int batchSize = 5000; // 每批5000个键
        int totalBatches = (int) Math.ceil((double) keyCount / batchSize);
        
        response.put("success", true);
        response.put("message", String.format("数据量很大(%d键)，建议分批导出", keyCount));
        response.put("exportInfo", Map.of(
            "totalKeys", keyCount,
            "batchSize", batchSize,
            "totalBatches", totalBatches,
            "batchUrl", "/api/redis/export/batch",
            "method", "batch"
        ));
        response.put("instructions", Map.of(
            "step1", "使用分批导出API: GET /api/redis/export/batch?batch=1&pattern=" + pattern + "&db=" + db,
            "step2", "依次导出每批数据，batch参数从1到" + totalBatches,
            "step3", "合并所有批次数据"
        ));
        
        return ResponseEntity.ok(response);
    }

    /**
     * 分批导出具体数据
     * @author Logan.Li
     */
    @GetMapping("/export/batch")
    public ResponseEntity<Map<String, Object>> exportBatch(
            @RequestParam(defaultValue = "1") int batch,
            @RequestParam(defaultValue = "*") String pattern,
            @RequestParam(defaultValue = "0") int db,
            @RequestParam(defaultValue = "5000") int batchSize) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            Set<String> allKeys = redisTemplate.keys(pattern);
            List<String> keysList = new ArrayList<>(allKeys);
            
            // 计算当前批次的键范围
            int startIndex = (batch - 1) * batchSize;
            int endIndex = Math.min(startIndex + batchSize, keysList.size());
            
            if (startIndex >= keysList.size()) {
                response.put("success", false);
                response.put("message", "批次超出范围");
                connection.close();
                return ResponseEntity.ok(response);
            }
            
            List<String> batchKeys = keysList.subList(startIndex, endIndex);
            Map<String, Object> batchData = new HashMap<>();
            int successCount = 0;
            
            for (String key : batchKeys) {
                try {
                    String value = redisService.getString(key);
                    if (value != null) {
                        batchData.put(key, value);
                        successCount++;
                    }
                } catch (Exception e) {
                    System.err.println("导出键 " + key + " 失败: " + e.getMessage());
                }
            }
            
            connection.close();
            
            response.put("success", true);
            response.put("data", batchData);
            response.put("batchInfo", Map.of(
                "currentBatch", batch,
                "batchSize", batchSize,
                "totalKeys", allKeys.size(),
                "batchKeys", batchKeys.size(),
                "successCount", successCount,
                "hasMore", endIndex < keysList.size()
            ));
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            response.put("success", false);
            response.put("message", "分批导出失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 批量导入缓存数据
     * @param importData 导入的JSON数据
     * @param db 数据库索引
     * @author Logan.Li
     */
    @PostMapping("/import")
    public ResponseEntity<Map<String, Object>> importCache(
            @RequestBody Map<String, Object> requestData,
            @RequestParam(defaultValue = "0") int db) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 获取导入数据
            Object importDataObj = requestData.get("data");
            if (importDataObj == null) {
                response.put("success", false);
                response.put("message", "导入数据不能为空");
                return ResponseEntity.ok(response);
            }
            
            // 切换数据库
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.select(db);
            
            int successCount = 0;
            int errorCount = 0;
            int skipCount = 0;
            
            // 处理导入数据
            if (importDataObj instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> importMap = (Map<String, Object>) importDataObj;
                
                // 限制导入数量，避免内存溢出
                int maxImportKeys = isProductionEnvironment() ? 1000 : 5000;
                if (importMap.size() > maxImportKeys) {
                    response.put("success", false);
                    response.put("message", "导入数据量过大，请分批导入。当前 " + importMap.size() + " 个键，最大允许 " + maxImportKeys + " 个");
                    connection.close();
                    return ResponseEntity.ok(response);
                }
                
                for (Map.Entry<String, Object> entry : importMap.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    
                    try {
                        // 检查键是否已存在
                        if (redisTemplate.hasKey(key)) {
                            skipCount++;
                            continue; // 跳过已存在的键，避免覆盖
                        }
                        
                        // 根据值的类型设置缓存
                        if (value instanceof String) {
                            redisTemplate.opsForValue().set(key, value);
                        } else if (value instanceof List) {
                            redisTemplate.opsForList().rightPushAll(key, ((List<?>) value).toArray());
                        } else if (value instanceof Map) {
                            redisTemplate.opsForHash().putAll(key, (Map<?, ?>) value);
                        } else if (value instanceof Set) {
                            redisTemplate.opsForSet().add(key, ((Set<?>) value).toArray());
                        } else {
                            // 其他类型转为字符串存储
                            redisTemplate.opsForValue().set(key, value.toString());
                        }
                        
                        successCount++;
                    } catch (Exception e) {
                        errorCount++;
                        System.out.println("导入键 " + key + " 失败: " + e.getMessage());
                    }
                }
            } else {
                response.put("success", false);
                response.put("message", "导入数据格式错误，应为JSON对象格式");
                connection.close();
                return ResponseEntity.ok(response);
            }
            
            connection.close();
            
            response.put("success", true);
            response.put("message", String.format("导入完成，成功: %d，跳过: %d，失败: %d", 
                successCount, skipCount, errorCount));
            response.put("data", Map.of(
                "successCount", successCount,
                "skipCount", skipCount,
                "errorCount", errorCount
            ));
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            response.put("success", false);
            response.put("message", "导入失败: " + e.getMessage());
            response.put("data", new HashMap<>());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 判断是否为生产环境
     * @author Logan.Li
     */
    private boolean isProductionEnvironment() {
        String[] activeProfiles = environment.getActiveProfiles();
        return Arrays.asList(activeProfiles).contains("prod") || 
               Arrays.asList(activeProfiles).contains("production");
    }
}
